package net.sk.china.common.utils;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * +----------------------------------------------------------------------
 * | Talk To [ 聊来改善地区金融服务环境，助力企业发展 ]
 * +----------------------------------------------------------------------
 * | Copyright (c) 2018-2024 聊来All rights reserved.
 * +----------------------------------------------------------------------
 * | Licensed ( <a href="http://www.apache.org/licenses/LICENSE-2.0">apache</a> )
 * +----------------------------------------------------------------------
 * | @Author: 聊来 <18970881148@qq.com>
 * +----------------------------------------------------------------------
 * | DateTime: 2024/6/2 14:31
 * +----------------------------------------------------------------------
 */

@Component
public class RestTemplateUtil {
    private final RestTemplate restTemplate;

    private static final String WXPAYSDK_VERSION = "WXPaySDK/3.0.9";
    private static final String USER_AGENT = WXPAYSDK_VERSION +
            " (" + System.getProperty("os.arch") + " " + System.getProperty("os.name") + " " + System.getProperty("os.version") +
            ") Java/" + System.getProperty("java.version") + " HttpClient/" + HttpClient.class.getPackage().getImplementationVersion();

    public RestTemplateUtil(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    /**
     * 发送GET请求
     * @param url 请求地址
     * @return JSONObject
     */
    public JSONObject getData(String url) {
        HttpHeaders headers = new HttpHeaders();
        headers.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36");
        headers.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>( headers);

        return restTemplate.exchange(url, HttpMethod.GET, requestEntity, JSONObject.class).getBody();
    }

    /**
     * 发送GET请求 支持header
     * @param url 接口地址
     * @param hashMap 请求参数
     * @return {@code JSONObject}
     */
    public JSONObject getData(String url, HashMap<String, String> hashMap) {

        HttpHeaders headers = new HttpHeaders();
        headers.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36");
        headers.setContentType(MediaType.APPLICATION_JSON);

        for (Map.Entry<String, String> entry : hashMap.entrySet()) {
            headers.add(entry.getKey(), entry.getValue());
        }

        HttpEntity<Map<String, Object>> requestEntity =
                new HttpEntity<>( headers);

        return restTemplate.exchange( url, HttpMethod.GET, requestEntity, JSONObject.class).getBody();
    }

    /**
     * 发送DELETE请求
     * @param url 请求地址
     * @return JSONObject
     */
    public JSONObject deleteData(String url) {
        HttpHeaders headers = new HttpHeaders();
        headers.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36");
        headers.setContentType(MediaType.TEXT_PLAIN);
        HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>( headers);

        return restTemplate.exchange(url, HttpMethod.DELETE, requestEntity, JSONObject.class).getBody();
    }

    /**
     * 发送POST请求
     * @param url 接口地址
     * @param map 请求参数
     * @return {@code String}
     */
    public String postFormData(String url, MultiValueMap<String, String> map) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.add("Accept",MediaType.TEXT_PLAIN_VALUE);
        HttpEntity<MultiValueMap<String, String>> requests = new HttpEntity<MultiValueMap<String, String>>(map, headers);

        return restTemplate.postForEntity(url, requests, String.class).getBody();
    }

    /**
     * 发送POST请求
     * @param url 接口地址
     * @param param 请求参数
     * @return byte[]
     */
    public byte[] postJsonDataAndReturnBuffer(String url, JSONObject param) {
        HttpHeaders headers = new HttpHeaders();

        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36");
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());

        HttpEntity<JSONObject> requestEntity = new HttpEntity<>(param, headers);

        return restTemplate.postForEntity(url, requestEntity, byte[].class).getBody();
    }

    /**
     * 发送POST请求
     * @param url 接口地址
     * @param param 请求参数
     * @return {@code String}
     */
    public String postJsonData(String url, JSONObject param) {

        HttpHeaders headers = new HttpHeaders();

        headers.setContentType(MediaType.APPLICATION_JSON);

        headers.add("Accept", MediaType.APPLICATION_JSON.toString());

        HttpEntity<JSONObject> requestEntity = new HttpEntity<>(param, headers);

        return restTemplate.postForEntity(url, requestEntity, String.class).getBody();
    }


    /**
     * 发送POST请求
     * @param url 接口地址
     * @param param 请求参数
     * @return {@code String}
     */
    public String postMapData(String url, Map<String, Object> param) {

        HttpHeaders headers = new HttpHeaders();
        headers.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36");
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add("Accept", MediaType.APPLICATION_JSON.toString());

        HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(param, headers);

        return restTemplate.postForEntity(url, requestEntity, String.class).getBody();

    }

    /**
     * 个推POST请求
     * @param url 接口地址
     * @param token 鉴权TOKEN
     * @param params 请求参数
     * @return {@code String}
     */
    public String postJsonData(String url, String token, JSONObject params) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add("token", token);

        HttpEntity<JSONObject> requestEntity = new HttpEntity<>(params, headers);

        ResponseEntity<String> response = restTemplate.postForEntity(url, requestEntity, String.class);

        return response.getBody();
    }


    /**
     * GET接口请求
     * @param url 接口地址
     * @param header header参
     * @return HttpEntity
     * @throws Exception
     */
    public org.apache.http.HttpEntity doGet(String url, Map<String, String> header) throws Exception {

        HttpClient httpClient = HttpClientBuilder.create().build();

        HttpGet request = new HttpGet(url);
        for (Map.Entry<String, String> e : header.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        return httpClient.execute(request).getEntity();
    }

    /**
     * POST接口请求
     * @param url 接口地址
     * @param header header参数
     * @param params 请求参数
     * @return HttpEntity
     * @throws Exception
     */
    public org.apache.http.HttpEntity doPost(String url, Map<String, String> header, String params) throws Exception {

        HttpClient httpClient = HttpClientBuilder.create().build();

        HttpPost request = new HttpPost(url);
        for (Map.Entry<String, String> e : header.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        if (StrUtil.isNotBlank(params)) {
            request.setEntity(new StringEntity(params, "utf-8"));
        }

        return httpClient.execute(request).getEntity();
    }

    /**
     * 发送POST请求
     * @param url 接口地址
     * @param xml xml数据
     * @return String
     */
    public String postXml(String url, String xml){
        HttpHeaders headers = new HttpHeaders();

        MediaType type = MediaType.parseMediaType("application/xml; charset=UTF-8");
        headers.setContentType(type);
        HttpEntity<String> requestEntity = new HttpEntity<>(xml, headers);

        ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, requestEntity, String.class);
        try{
//            System.out.println("responseEntity"+responseEntity);
            return new String(Objects.requireNonNull(responseEntity.getBody()).getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8);
        }catch (Exception e){
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 发送POST-JSON请求(微信退款专用)
     * @param url 请求地址
     * @param xml xml数据
     * @param mchId 商户ID
     * @param path 证书路径
     * @return String
     */
    public String postWxRefundXml(String url, String xml, String mchId, String path) throws Exception {
        KeyStore clientStore = KeyStore.getInstance("PKCS12");
        // 读取本机存放的PKCS12证书文件
        FileInputStream inStream = new FileInputStream(path);
        try {
            // 指定PKCS12的密码(商户ID)
            clientStore.load(inStream, mchId.toCharArray());
        } finally {
            inStream.close();
        }

        // 实例化密钥库 & 初始化密钥工厂
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(clientStore, mchId.toCharArray());

        // 创建 SSLContext
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());

        SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
                sslContext,
                new String[]{"TLSv1"},
                null,
                new DefaultHostnameVerifier());

        BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager(
                RegistryBuilder.<ConnectionSocketFactory>create()
                        .register("http", PlainConnectionSocketFactory.getSocketFactory())
                        .register("https", sslConnectionSocketFactory)
                        .build(),
                null,
                null,
                null
        );

        HttpClient httpClient = HttpClientBuilder.create()
                .setConnectionManager(connManager)
                .build();

        HttpPost httpPost = new HttpPost(url);

        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(8*1000).setConnectTimeout(6*1000).build();
        httpPost.setConfig(requestConfig);

        StringEntity postEntity = new StringEntity(xml, "UTF-8");
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.addHeader("User-Agent", USER_AGENT + " " + mchId);
        httpPost.setEntity(postEntity);

        HttpResponse httpResponse = httpClient.execute(httpPost);
        org.apache.http.HttpEntity httpEntity = httpResponse.getEntity();
        return EntityUtils.toString(httpEntity, "UTF-8");
    }
}
